<script>
import { reactive, watch, nextTick } from "vue";
import { getDicMap, getColdCompany } from "@/utils/storage";
import { useTzRouter } from "@/vhooks/useTzRouter";
import Taro from "@tarojs/taro";
import { querySettingApi, queryBoxingApi } from "./api";

export default {
  name: "BoxingInfo",
  components: {},
  setup() {
    const { route, navigateTo, navigateBack } = useTzRouter();
    const {
      userType,
      boxingSizeTypeList,
      boxingSizeCodeList,
      fullOrEmptyCodeList,
      boxingSealedTypeList,
      boxingSealedNameList,
    } = getDicMap();

    const state = reactive({
      // 集装箱数据
      formModel: {
        boxingSourceCode: "5", // 来源默认值
      },
      showSeleadBtn: false,
      boxingIndex: route.query?.boxingIndex, // 已添加的集装箱index
    });

    // 路由参数
    const { truckPayloadType, boxingIds, sizeTypes, truckType } = route.query;

    state.boxingIds = boxingIds;
    state.sizeTypes = sizeTypes ? sizeTypes.split(",") : [];
    state.truckPayloadType = truckPayloadType
      ? JSON.parse(truckPayloadType)
      : null;

    state.truckType = truckType ? JSON.parse(truckType) : null;
    state.trailerWeight = route.query.trailerWeight; // 架重

    // 数据回显
    if (route.query.boxingInfo) {
      state.isEdit = true;
      const tempBoxingInfo = JSON.parse(route.query.boxingInfo);
      state.formModel = { ...state.formModel, ...tempBoxingInfo };
    }

    // 是否有带封志信息
    if (route.query.sealed) {
      // 如果编辑时，页面的封志信息和缓存中基础数据的完全一致时，需要默认勾上
      const sealed = JSON.parse(route.query.sealed);
      if (
        sealed.boxingSealed === (state.formModel.boxingSealed || "") &&
        sealed.boxingSealedType === (state.formModel.boxingSealedType || "") &&
        sealed.boxingSealedName === (state.formModel.boxingSealedName || "")
      ) {
        state.boxingSealed_checked = true;
      }
      state.showSeleadBtn = true;
      state.sealed = route.query.sealed;
    }

    // 设置默认值
    if (state.truckPayloadType.isHeavyCar) {
      // 重车默认重箱
      state.formModel.fullOrEmptyCode = "5";
    }

    // 获取 setting 数据，在做保存校验的时候使用
    !userType.isPersonal &&
      querySettingApi(["TONS_BOXING_WT", "TANK_BOXING_WT"]).then((res) => {
        const obj = {};
        res.data.forEach((item) => {
          obj[item.configId] = item.configValue;
        });
        state.setting = obj;
      });
    // --- 原有的校验方法
    /**
     * 校验集装箱号是否符合国际标准
     * @param {string} boxingCode 集装箱号
     */
    const checkBoxingCode = (boxingCode) => {
      if (!boxingCode || boxingCode.length !== 11) {
        return false;
      }
      const daima = boxingCode.substr(0, 4);
      // 集装箱号前四位后面的
      const boxingCodeRest = boxingCode.substr(4);
      //获取代码的每位计算值
      const char1 = daima.substr(0, 1);
      const i1 = changevalue(char1);
      const char2 = daima.substr(1, 1);
      const i2 = changevalue(char2);
      const char3 = daima.substr(2, 1);
      const i3 = changevalue(char3);
      const char4 = daima.substr(3, 1);
      const i4 = changevalue(char4);
      //获取7位箱号的计算值
      const int1 = boxingCodeRest.substr(0, 1);
      const int2 = boxingCodeRest.substr(1, 1);
      const int3 = boxingCodeRest.substr(2, 1);
      const int4 = boxingCodeRest.substr(3, 1);
      const int5 = boxingCodeRest.substr(4, 1);
      const int6 = boxingCodeRest.substr(5, 1);
      const int7 = boxingCodeRest.substr(6, 1);
      //计算值求和并对11取余，和第七位箱号对比
      const sum =
        i1 +
        2 * i2 +
        4 * i3 +
        8 * i4 +
        16 * int1 +
        32 * int2 +
        64 * int3 +
        128 * int4 +
        256 * int5 +
        512 * int6;
      const result = sum % 11;
      // NOTE: 如果集装箱号前四位后面有非数字，这里的result 为 NaN
      // NaN 的 toString 为 "NaN"
      if (result.toString() === int7 || result.toString() - int7 === 10) {
        return true;
      } else {
        return false;
      }
    };
    /**
     * 根据字母获取对应的数字
     * @param {string} str 字符串
     */
    const changevalue = (str) => {
      if (str === "a" || str === "A") return 10;
      else if (str === "b" || str === "B") return 12;
      else if (str === "c" || str === "C") return 13;
      else if (str === "d" || str === "D") return 14;
      else if (str === "e" || str === "E") return 15;
      else if (str === "f" || str === "F") return 16;
      else if (str === "g" || str === "G") return 17;
      else if (str === "h" || str === "H") return 18;
      else if (str === "i" || str === "I") return 19;
      else if (str === "j" || str === "J") return 20;
      else if (str === "k" || str === "K") return 21;
      else if (str === "l" || str === "L") return 23;
      else if (str === "m" || str === "M") return 24;
      else if (str === "n" || str === "N") return 25;
      else if (str === "o" || str === "O") return 26;
      else if (str === "p" || str === "P") return 27;
      else if (str === "q" || str === "Q") return 28;
      else if (str === "r" || str === "R") return 29;
      else if (str === "s" || str === "S") return 30;
      else if (str === "t" || str === "T") return 31;
      else if (str === "u" || str === "U") return 32;
      else if (str === "v" || str === "V") return 34;
      else if (str === "w" || str === "W") return 35;
      else if (str === "x" || str === "X") return 36;
      else if (str === "y" || str === "Y") return 37;
      else if (str === "z" || str === "Z") return 38;
      else return -1000;
    };

    /**
     * 是否为空字符串
     */
    const isEmpty = (str) => {
      if (typeof str === "number") {
        str = str.toString();
      }
      return (
        str === null || str === undefined || str.trim() === "" || str === "null"
      );
    };

    /**
     * 通过系统配置项校验集装箱重量
     * @param {string} boxingWeight 集装箱重量
     * @param {string} setting 配置项
     */
    const checkBoxingWeightBySetting = (boxingWeight, setting) => {
      if (setting.indexOf("~") === -1) {
        return true;
      }
      boxingWeight = parseInt(boxingWeight);
      const wtArr = setting.split("~");
      const minWt = parseInt(wtArr[0]);
      const maxWt = parseInt(wtArr[1]);
      return !(boxingWeight < minWt || boxingWeight > maxWt);
    };
    // ---

    // 校验集装箱总类型尺寸是否超过限制
    const checkTotalSizeType = (currSizeType) => {
      let anotherSizeType = "";
      if (state.sizeTypes.length === 2) {
        /**
         * 存在两条数据，这种情况肯定是编辑已有数据
         * 会存在指向对应集装箱的下标 boxingIndex
         * 所以直接获取另外一条的类型尺寸
         */
        const anotherIndex = [1, 0][+state.boxingIndex];
        anotherSizeType = state.sizeTypes[anotherIndex];
      } else if (state.sizeTypes.length === 1) {
        /**
         * 存在一条数据，判断是否存在 boxingIndex
         * 存在 boxingIndex 说明是编辑已有数据，不管控
         * 不存在则是新增
         */
        if (!state.boxingIndex) {
          anotherSizeType = state.sizeTypes[0];
        }
      }

      if (anotherSizeType) {
        /**
         * 存在有另外一个集装箱值的情况下，判断两个类型尺寸是否都为2开头
         * 只要有一个不为2开头则是超出了限制
         */
        return (
          +anotherSizeType.substr(0, 1) === 2 &&
          +currSizeType.substr(0, 1) === 2
        );
      }
      return true;
    };

    const checkFormData = (data) => {
      const {
        boxingCode,
        boxingSizeType,
        boxingSourceCode,
        boxingWeight,
        fullOrEmptyCode,
        boxingSealed,
        boxingSealedType,
        boxingSealedName,
      } = data;
      try {
        // 集装箱号
        if (isEmpty(boxingCode)) {
          throw new Error("请输入集装箱号");
        }
        // 校验集装箱号是否已经存在，编辑原有数据不校验
        if (
          !state.isEdit &&
          boxingIds &&
          boxingIds.length &&
          boxingIds.includes(boxingCode)
        ) {
          throw new Error("集装箱号已存在");
        }
        if (isEmpty(boxingSizeType)) {
          throw new Error("请选择集装箱类型尺寸");
        }
        if (isEmpty(boxingSourceCode)) {
          throw new Error("请选择集装箱来源");
        }
        if (isEmpty(boxingWeight)) {
          throw new Error("请输入集装箱重量");
        }
        if (!checkTotalSizeType(boxingSizeType)) {
          throw new Error("两个集装箱时，类型尺寸只能选择2开头的尺寸");
        }

        if (!userType.isPersonal) {
          let limitWeight = "";
          if (state.truckType.isContainer) {
            // 货柜车
            limitWeight = state.setting["TANK_BOXING_WT"];
          } else {
            // 吨车
            limitWeight = state.setting["TONS_BOXING_WT"];
          }
          if (limitWeight) {
            // 通过系统配置项校验集装箱重量
            if (!checkBoxingWeightBySetting(boxingWeight, limitWeight)) {
              throw new Error(`集装箱重量不在${limitWeight}范围内`);
            }
          }
        }

        if (state.truckPayloadType.isHeavyCar) {
          if (isEmpty(fullOrEmptyCode)) {
            throw new Error("请选择集装箱 重箱/空箱");
          }
          if (
            !isEmpty(boxingSealed) ||
            !isEmpty(boxingSealedType) ||
            !isEmpty(boxingSealedName)
          ) {
            if (isEmpty(boxingSealed)) {
              throw new Error("请输入封志号");
            }
            if (isEmpty(boxingSealedType)) {
              throw new Error("请选择封志类型");
            }
            if (isEmpty(boxingSealedName)) {
              throw new Error("请选择施封人");
            }
          }
          //如果填写了集装箱信息，那么封志信息就必填
          if (state.truckType.isTon) {
            if (
              isEmpty(boxingSealed) ||
              isEmpty(boxingSealedType) ||
              isEmpty(boxingSealedName)
            ) {
              throw new Error("请填写封志信息");
            }
          }
        }
        return true;
      } catch (err) {
        $TzNotify.danger(err.message);
        return false;
      }
    };

    const handleSave = async () => {
      // 表单校验
      if (!checkFormData(state.formModel)) return;

      const { boxingCode, boxingWeight } = state.formModel;
      // 校验集装箱号是否符合国际标准
      if (!checkBoxingCode(boxingCode)) {
        const confirmBoxingCodeRes = await Taro.showModal({
          content:
            "集装箱号[" + boxingCode + "]不符合国际集装箱编号标准，是否继续?",
          confirmText: "是",
          cancelText: "否",
        });
        if (!confirmBoxingCodeRes.confirm) return;
      }

      if (state.trailerWeight && state.trailerWeight === boxingWeight) {
        const confirmBoxingWeightRes = await Taro.showModal({
          content: "架重与自重相同，是否需要修改?",
          confirmText: "是",
          cancelText: "否",
        });
        // 需要修改，确认就不往下走
        if (confirmBoxingWeightRes.confirm) return;
      }

      const { isHasBoxEmptyCar, isHeavyCar } = state.truckPayloadType;
      if ((isHasBoxEmptyCar || isHeavyCar) && boxingWeight.length > 4) {
        const confirmOverWeightRes = await Taro.showModal({
          content: "柜重超过4位，是否继续?",
          confirmText: "是",
          cancelText: "否",
        });
        if (!confirmOverWeightRes.confirm) return;
      }
      const params = { ...state.formModel, boxingIndex: state.boxingIndex };
      if (state.boxingSealed_checked) {
        // 勾选了调取按钮
        params.boxingSealed_checked = state.boxingSealed_checked;
      }
      navigateBack({
        delta: 1,
        event: {
          type: "boxInfoAddBack",
          data: params,
        },
      });
    };

    const inputRender = (keyName, attrs, rightRender) => {
      return () => (
        <tz-view class="cell-content">
          <tz-input v-model={state.formModel[keyName]} {...attrs}></tz-input>
          {rightRender && typeof rightRender === "function" && rightRender()}
        </tz-view>
      );
    };

    const pickerRender = ({ keyName, range, handleChange }) => {
      return () => (
        <tz-picker
          v-model={state.formModel[keyName]}
          mode="selector"
          range={range}
          rangeKey="para_name"
          valueKey="para_value"
          onChange={(e) => {
            typeof handleChange === "function" && handleChange(e);
          }}
        ></tz-picker>
      );
    };

    // isOnInput 判断是否从 onInput 调用
    const searchBoxing = (boxingCode, isOnInput) => {
      boxingCode = boxingCode || state.formModel.boxingCode;
      if (isEmpty(boxingCode)) {
        Taro.showToast({
          title: "请输入集装箱号",
          icon: "none",
          duration: 1000,
        });
        return;
      }
      queryBoxingApi({
        boxingCode,
      })
        .then((res) => {
          const { boxingSizeType, boxingSourceCode, boxingWeight } = res.data;
          state.formModel.boxingSizeType = boxingSizeType || "0";
          state.formModel.boxingSourceCode = boxingSourceCode || "0";
          state.formModel.boxingWeight = boxingWeight
            ? boxingWeight.toString()
            : "";
        })
        .catch(() => {
          !isOnInput &&
            Taro.showToast({
              title: "无法查询集装箱信息，请去基础数据维护",
              icon: "none",
              duration: 2000,
            });
        });
    };

    const cellRender = () => {
      const formConfig = [
        {
          title: "集装箱号",
          content: inputRender(
            "boxingCode",
            {
              type: "text",
              placeholder: "请输入集装箱号",
              maxlength: "11",
              rules: (val) => {
                const value = val?.match(/[a-zA-Z0-9\-]{0,11}/g)?.[0] || "";
                if (value.length === 11 && !userType.isPersonal) {
                  searchBoxing(value, 1);
                }
                return value.toUpperCase();
              },
            },
            () => {
              return userType.isDriver || userType.isOperator ? (
                <tz-icon name="search" onClick={() => searchBoxing()}></tz-icon>
              ) : (
                ""
              );
            }
          ),
        },
        {
          title: "类型尺寸",
          content: pickerRender({
            keyName: "boxingSizeType",
            range: boxingSizeTypeList,
            handleChange(e) {
              if (
                !checkTotalSizeType(
                  boxingSizeTypeList[e.detail.value].para_value
                )
              ) {
                $TzNotify.danger("两个集装箱时，类型尺寸只能选择2开头的尺寸");
              }
            },
          }),
        },
        {
          title: "来源",
          content: pickerRender({
            keyName: "boxingSourceCode",
            range: boxingSizeCodeList,
          }),
        },
      ];

      state.truckPayloadType.isHeavyCar &&
        formConfig.push({
          title: "重箱/空箱",
          content: pickerRender({
            keyName: "fullOrEmptyCode",
            range: fullOrEmptyCodeList,
          }),
        });

      formConfig.push({
        title: "自重(KG)",
        content: inputRender("boxingWeight", {
          type: "number",
          placeholder: "请输入自重(KG)",
          maxlength: "5",
        }),
      });

      const fetchSealed = () => {
        state.boxingSealed_checked = !state.boxingSealed_checked;
        if (!route.query.sealed) return;
        const sealed = JSON.parse(route.query.sealed);

        if (state.boxingSealed_checked) {
          // 勾选
          const { boxingSealed, boxingSealedType, boxingSealedName } = sealed;
          state.formModel.boxingSealed = boxingSealed;
          state.formModel.boxingSealedType = boxingSealedType;
          state.formModel.boxingSealedName = boxingSealedName;
          // 重车吨车时，集装箱信息填写默认值
          if (state.truckType.isTon && state.truckPayloadType.isHeavyCar) {
            if (route.query.truckLicenseCode) {
              state.formModel.boxingCode = route.query.truckLicenseCode;
            }
            // 自重
            state.formModel.boxingWeight = "0";
            // 来源 默认 '第三方提供箱'
            state.formModel.boxingSourceCode = "5";
            // 重箱/空箱 默认 '重箱'
            state.formModel.fullOrEmptyCode = "5";
            // 集装箱尺寸默认'22G1'
            state.formModel.boxingSizeType = "22G1";
          }
        } else {
          // 清空默认值
          state.formModel.boxingSealed = "";
          state.formModel.boxingSealedType = "";
          state.formModel.boxingSealedName = "";
          if (state.truckType.isTon && state.truckPayloadType.isHeavyCar) {
            state.formModel.boxingCode = "";
            state.formModel.boxingWeight = "";
            state.formModel.boxingSourceCode = "0";
            state.formModel.fullOrEmptyCode = "0";
            state.formModel.boxingSizeType = "0";
          }
        }
      };

      state.truckPayloadType.isHeavyCar &&
        formConfig.push(
          ...[
            {
              title: "封志号",
              content: inputRender(
                "boxingSealed",
                {
                  type: "text",
                  placeholder: "请输入电子关锁号",
                  maxlength: "14",
                },
                () => {
                  return (
                    <tz-view class="suffix-t-switch">
                      {!userType.isPersonal && state.showSeleadBtn && (
                        <>
                          <tz-switch
                            onChange={() => fetchSealed()}
                            type="checkbox"
                            v-model={state.boxingSealed_checked}
                          ></tz-switch>
                          <tz-text onClick={() => fetchSealed()}>调取</tz-text>
                        </>
                      )}
                    </tz-view>
                  );
                }
              ),
            },
            {
              title: "封志类型",
              content: pickerRender({
                keyName: "boxingSealedType",
                range: boxingSealedTypeList,
              }),
            },
            {
              title: "施封人",
              content: pickerRender({
                keyName: "boxingSealedName",
                range: boxingSealedNameList,
              }),
            },
          ]
        );

      return () =>
        formConfig.map((item) => (
          <tz-cell title={item.title}>{item.content()}</tz-cell>
        ));
    };

    const handleDel = () => {
      Taro.showModal({
        content: "确定删除该条记录吗?",
        confirmText: "确定",
        cancelText: "取消",
      }).then((res) => {
        if (res.confirm) {
          navigateBack({
            delta: 1,
            event: {
              type: "deleteBoxingInfo", // 删除集装箱数据
              data: { boxingCode: state.formModel.boxingCode },
            },
          });
        }
      });
    };

    return () => {
      return (
        <tz-view class="boxing-info">
          <tz-view class="form-content">
            <tz-view class="base-info">{cellRender()}</tz-view>
          </tz-view>

          <tz-view class="btn-block">
            {state.isEdit && (
              <tz-button
                class="del-btn"
                type="danger"
                onClick={() => handleDel()}
              >
                删除
              </tz-button>
            )}
            <tz-button
              class="submit-btn"
              type="primary"
              onClick={() => handleSave()}
            >
              保存
            </tz-button>
          </tz-view>
        </tz-view>
      );
    };
  },
};
</script>

<style lang="scss">
.boxing-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  .form-content {
    width: 100%;
    background: #fff;
    border-top: 1px solid #d9d9d9;
    padding: 0 15px;
    .base-info {
      .cell-content {
        display: flex;
        align-items: center;
        .tz-input {
          flex: 1;
        }
      }
      .tz-cell-label {
        width: 100px;
      }
      .tz-cell-value {
        .letter-t {
          margin-right: 20px;
        }
        .suffix-t-switch {
          // width: 100%;
          display: flex;
          justify-content: flex-end;
          align-items: center;
          .tz-switch {
            display: inline-flex;
          }
        }
      }
    }
  }

  .btn-block {
    width: 345px;
    margin-top: 20px;
    display: flex;
    justify-content: center;
    .del-btn {
      flex: 1;
      margin-right: 20px;
    }
    .submit-btn {
      flex: 1;
    }
  }
}
</style>
